home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / ispell40.lha / ispell-4.0 / suf.c < prev    next >
C/C++ Source or Header  |  1993-04-15  |  13KB  |  863 lines

  1. /* Copyright (C) 1990, 1993 Free Software Foundation, Inc.
  2.  
  3.    This file is part of GNU ISPELL.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "ispell.h"
  22. #include "hash.h"
  23. #include "good.h"
  24. #include "build.h"
  25. #include "charset.h"
  26.  
  27. #ifdef FPROTO
  28. int d_ending (char *, int);
  29. int t_ending (char *, int);
  30. int r_ending (char *, int);
  31. int g_ending (char *, int);
  32. int h_ending (char *, int);
  33. int s_ending (char *, int);
  34. int n_ending (char *, int);
  35. int e_ending (char *, int);
  36. int y_ending (char *, int);
  37. #else
  38. int d_ending ();
  39. int t_ending ();
  40. int r_ending ();
  41. int g_ending ();
  42. int h_ending ();
  43. int s_ending ();
  44. int n_ending ();
  45. int e_ending ();
  46. int y_ending ();
  47. #endif
  48.  
  49. struct hash_table_entry null_hte;
  50.  
  51. static entering = 0;
  52.  
  53. void
  54. reapone (n)
  55.   int n;
  56. {
  57.   int i;
  58.   entering = 1;
  59.   for (i = 0; i < n; i++)
  60.     {
  61.       if (lookup (words[i]) ||
  62.       sufcheck (words[i], strlen (words[i])))
  63.     {
  64.       words[i][0] = 0;
  65.     }
  66.     }
  67.   entering = 0;
  68. }
  69.  
  70. void
  71. reap (h)
  72.      hash_index h;
  73. {
  74.   struct hash_table_entry hte;
  75.   int i, n;
  76.   char *entry;
  77.  
  78.   hash_retrieve (h, &hte);
  79.   if (hte.next >= HASH_SPECIAL && hte.next != HASH_END)
  80.     return;
  81.   null_hte.next = hte.next;
  82.   hash_store (h, &null_hte);
  83.  
  84.   entry = htetostr (&hte, h);
  85.   n = expand (entry);
  86.  
  87.   reapone (n);
  88.  
  89.   for (i = 0; i < n; i++)
  90.     if (words[i][0])
  91.       break;
  92.  
  93.   if (i != n)
  94.     {
  95.       /* still some word that wasn't taken care of */
  96.       hash_store (h, &hte);
  97.     }
  98. }
  99.  
  100. void
  101. reapall ()
  102. {
  103.   hash_index h;
  104.   for (h = 1; h < hashsize; h++)
  105.     reap (h);
  106. }
  107.  
  108. hash_index
  109. lookup (w)
  110.      char *w;
  111. {
  112.   comp_char outbuf[MAX_WORD_LEN];
  113.   int len;
  114.   hash_index h;
  115.  
  116.   len = lexword (w, strlen (w), outbuf);
  117.  
  118.   if (len == 0)
  119.     return (0);
  120.  
  121.   h = hash_lookup (outbuf, len);
  122.   return (h);
  123. }
  124.  
  125. void
  126. add_flag (h, flag)
  127.   hash_index h;
  128.   unsigned short flag;
  129. {
  130.   store_flags (h, get_flags (h) | flag);
  131. }
  132.  
  133.  
  134. int
  135. sufcheck (w, len)
  136.   char *w;
  137.   int len;
  138. {
  139.   char w1[MAX_WORD_LEN];
  140.   char *p, *q;
  141.   int n;
  142.   int c;
  143.  
  144.   if (len < 4)
  145.     return (0);
  146.  
  147.   for (p = w, q = w1, n = len; n-- && *p; p++, q++)
  148.     {
  149.       c = charset[(unsigned int) *p].lowercase;
  150.       if (c)
  151.     *q = c;
  152.       else
  153.     *q = *p;
  154.     }
  155.   *q = 0;
  156.   switch (w1[len - 1])
  157.     {
  158.     case 'd':
  159.       return (d_ending (w1, len));
  160.     case 't':
  161.       return (t_ending (w1, len));
  162.     case 'r':
  163.       return (r_ending (w1, len));
  164.     case 'g':
  165.       return (g_ending (w1, len));
  166.     case 'h':
  167.       return (h_ending (w1, len));
  168.     case 's':
  169.       return (s_ending (w1, len));
  170.     case 'n':
  171.       return (n_ending (w1, len));
  172.     case 'e':
  173.       return (e_ending (w1, len));
  174.     case 'y':
  175.       return (y_ending (w1, len));
  176.     default:
  177.       return (0);
  178.     }
  179. }
  180.  
  181. /* FOR CREATING, FIXING */
  182. int
  183. g_ending (w, len)
  184.   char *w;
  185.   int len;
  186. {
  187.   char *p;
  188.   hash_index h;
  189.  
  190.   p = w + len - 3;        /* if the word ends in 'ing', then *p == 'i' */
  191.  
  192.   if (p[0] != 'i')
  193.     return (0);
  194.   if (p[1] != 'n')
  195.     return (0);
  196.   if (p[2] != 'g')
  197.     return (0);
  198.  
  199.   p[0] = 'e';            /* change I to E, like in CREATING */
  200.   p[1] = 0;
  201.   len -= 2;
  202.  
  203.   if (len < 2)
  204.     return (0);
  205.  
  206.   if ((h = lookup (w)))
  207.     {
  208.       if (entering)
  209.     add_flag (h, G_FLAG);
  210.       if (get_flags (h) & G_FLAG)
  211.     return (2);
  212.     }
  213.  
  214.   p[0] = 0;
  215.   len -= 1;
  216.  
  217.   if (len < 2)
  218.     return (0);
  219.  
  220.   if (p[-1] == 'e')
  221.     return (0);            /* this stops CREATEING */
  222.  
  223.   if ((h = lookup (w)))
  224.     {
  225.       if (entering)
  226.     add_flag (h, G_FLAG);
  227.       if (get_flags (h) & G_FLAG)
  228.     return (2);
  229.     }
  230.   return (0);
  231. }
  232.  
  233. /* FOR CREATED, IMPLIED, CROSSED */
  234. int
  235. d_ending (w, len)
  236.   char *w;
  237.   int len;
  238. {
  239.   char *p;
  240.   hash_index h;
  241.  
  242.   p = w + len - 2;
  243.  
  244.   if (p[0] != 'e')
  245.     return (0);
  246.   if (p[1] != 'd')
  247.     return (0);
  248.  
  249.   p[1] = 0;            /* kill 'd' */
  250.   len--;
  251.  
  252.   /* like CREATED */
  253.   if ((h = lookup (w)))
  254.     {
  255.       if (entering)
  256.     add_flag (h, D_FLAG);
  257.       if (get_flags (h) & D_FLAG)
  258.     return (2);
  259.     }
  260.  
  261.   if (len < 3)
  262.     return (0);
  263.  
  264.   p[0] = 0;
  265.   p--;
  266.  
  267.   /* ED is now completely gone */
  268.  
  269.   if (p[0] == 'i' && !isvowel (p[-1]))
  270.     {
  271.       p[0] = 'y';
  272.       if ((h = lookup (w)))
  273.     {
  274.       if (entering)
  275.         add_flag (h, D_FLAG);
  276.       if (get_flags (h) & D_FLAG)
  277.         return (2);
  278.     }
  279.  
  280.       p[0] = 'i';
  281.     }
  282.  
  283.   if ((p[0] != 'e' && p[0] != 'y') ||
  284.       (p[0] == 'y' && isvowel (p[-1])))
  285.     {
  286.       if ((h = lookup (w)))
  287.     {
  288.       if (entering)
  289.         add_flag (h, D_FLAG);
  290.       if (get_flags (h) & D_FLAG)
  291.         return (2);
  292.     }
  293.     }
  294.  
  295.   return (0);
  296. }
  297.  
  298. /* FOR LATEST, DIRTIEST, BOLDEST */
  299. int
  300. t_ending (w, len)
  301.   char *w;
  302.   int len;
  303. {
  304.   char *p;
  305.   hash_index h;
  306.  
  307.   p = w + len - 3;
  308.  
  309.   if (p[0] != 'e')
  310.     return (0);
  311.   if (p[1] != 's')
  312.     return (0);
  313.   if (p[2] != 't')
  314.     return (0);
  315.  
  316.   p[1] = 0;            /* kill 's' */
  317.   len -= 2;
  318.  
  319.   if ((h = lookup (w)))
  320.     {
  321.       if (entering)
  322.     add_flag (h, T_FLAG);
  323.       if (get_flags (h) & T_FLAG)
  324.     return (2);
  325.     }
  326.  
  327.   if (len < 3)
  328.     return (0);
  329.  
  330.   p[0] = 0;
  331.   p--;
  332.  
  333.   /* EST is now completely gone */
  334.  
  335.   if (p[0] == 'i' && !isvowel (p[-1]))
  336.     {
  337.       p[0] = 'y';
  338.       if ((h = lookup (w)))
  339.     {
  340.       if (entering)
  341.         add_flag (h, T_FLAG);
  342.       if (get_flags (h) & T_FLAG)
  343.         return (2);
  344.     }
  345.       return (0);
  346.     }
  347.  
  348.   if ((p[0] != 'e' && p[0] != 'y') ||
  349.       (p[0] == 'y' && isvowel (p[-1])))
  350.     {
  351.       if ((h = lookup (w)))
  352.     {
  353.       if (entering)
  354.         add_flag (h, T_FLAG);
  355.       if (get_flags (h) & T_FLAG)
  356.         return (2);
  357.     }
  358.     }
  359.   return (0);
  360. }
  361.  
  362. /* FOR LATER, DIRTIER, BOLDER */
  363. int
  364. r_ending (w, len)
  365.   char *w;
  366.   int len;
  367. {
  368.   char *p;
  369.   hash_index h;
  370.  
  371.   p = w + len - 2;
  372.  
  373.   if (p[0] != 'e')
  374.     return (0);
  375.   if (p[1] != 'r')
  376.     return (0);
  377.  
  378.   p[1] = 0;            /* kill 'r' */
  379.   len--;
  380.  
  381.   if ((h = lookup (w)))
  382.     {
  383.       if (entering)
  384.     add_flag (h, R_FLAG);
  385.       if (get_flags (h) & R_FLAG)
  386.     return (2);
  387.     }
  388.  
  389.   if (len < 3)
  390.     return (0);
  391.  
  392.   p[0] = 0;
  393.   p--;
  394.  
  395.   /* ER is now completely gone */
  396.  
  397.   if (p[0] == 'i' && !isvowel (p[-1]))
  398.     {
  399.       p[0] = 'y';
  400.       if ((h = lookup (w)))
  401.     {
  402.       if (entering)
  403.         add_flag (h, R_FLAG);
  404.       if (get_flags (h) & R_FLAG)
  405.         return (2);
  406.     }
  407.       return (0);
  408.     }
  409.  
  410.   if ((p[0] != 'e' && p[0] != 'y') ||
  411.       (p[0] == 'y' && isvowel (p[-1])))
  412.     {
  413.       if ((h = lookup (w)))
  414.     {
  415.       if (entering)
  416.         add_flag (h, R_FLAG);
  417.       if (get_flags (h) & R_FLAG)
  418.         return (2);
  419.     }
  420.     }
  421.   return (0);
  422. }
  423.  
  424. /* FOR HUNDREDTH, TWENTIETH */
  425. int
  426. h_ending (w, len)
  427.   char *w;
  428.   int len;
  429. {
  430.   char *p;
  431.   hash_index h;
  432.  
  433.   p = w + len - 2;
  434.  
  435.   if (p[0] != 't')
  436.     return (0);
  437.   if (p[1] != 'h')
  438.     return (0);
  439.  
  440.   *p = 0;
  441.   p -= 2;
  442.  
  443.   if (p[0] == 'i' && p[1] == 'e')
  444.     {
  445.       p[0] = 'y';
  446.       p[1] = 0;
  447.     }
  448.   else
  449.     {
  450.       if (p[1] == 'y')
  451.     return (0);        /* stops myth -> my/h */
  452.     }
  453.  
  454.   if ((h = lookup (w)))
  455.     {
  456.       if (entering)
  457.     add_flag (h, H_FLAG);
  458.       if (get_flags (h) & H_FLAG)
  459.     return (2);
  460.     }
  461.  
  462.   return (0);
  463. }
  464.  
  465. /*
  466.  * check for flags: X, J, Z, S, P, M
  467.  *
  468.  * X    -ions or -ications or -ens
  469.  * J    -ings
  470.  * Z    -ers or -iers
  471.  * S    -ies or -es or -s
  472.  * P    -iness or -ness
  473.  * M    -'s
  474.  */
  475.  
  476. /* FOR ALL SORTS OF THINGS ENDING IN S */
  477. int
  478. s_ending (w, len)
  479.   char *w;
  480.   int len;
  481. {
  482.   char *p;
  483.   hash_index h;
  484.  
  485.   p = w + len;
  486.  
  487.   /* len >= 4 if we get here at all */
  488.  
  489.   if (p[-2] == '\'')
  490.     {
  491.       p[-2] = 0;
  492.       if ((h = lookup (w)))
  493.     {
  494.       if (entering)
  495.         add_flag (h, M_FLAG);
  496.       if (get_flags (h) & M_FLAG)
  497.         return (2);
  498.     }
  499.       return (0);
  500.     }
  501.   if (!issxzhy (p[-2]))
  502.     {
  503.       /* see if it was simple adding S */
  504.       p[-1] = 0;        /* kill S */
  505.       if ((h = lookup (w)))
  506.     {
  507.       if (entering)
  508.         add_flag (h, S_FLAG);
  509.       if (get_flags (h) & S_FLAG)
  510.         return (2);
  511.     }
  512.     }
  513.  
  514.   if (p[-2] == 'y')
  515.     {
  516.       if (!isvowel (p[-3]))
  517.     return (0);
  518.       p[-1] = 0;
  519.       if ((h = lookup (w)))
  520.     {
  521.       if (entering)
  522.         add_flag (h, S_FLAG);
  523.       if (get_flags (h) & S_FLAG)
  524.         return (2);
  525.     }
  526.       return (0);
  527.     }
  528.  
  529.   if (p[-2] == 'e')
  530.     {
  531.       if (issxzh (p[-3]))
  532.     {
  533.       p[-2] = 0;
  534.  
  535.       if ((h = lookup (w)))
  536.         {
  537.           if (entering)
  538.         add_flag (h, S_FLAG);
  539.           if (get_flags (h) & S_FLAG)
  540.         return (2);
  541.         }
  542.  
  543.       return (0);
  544.     }
  545.  
  546.       if (p[-3] == 'i')
  547.     {
  548.       if (isvowel (p[-4]))
  549.         return (0);
  550.       p[-3] = 'y';
  551.       p[-2] = 0;
  552.       if ((h = lookup (w)))
  553.         {
  554.           if (entering)
  555.         add_flag (h, S_FLAG);
  556.           if (get_flags (h) & S_FLAG)
  557.         return (2);
  558.         }
  559.     }
  560.       return (0);
  561.     }
  562.  
  563.   if (p[-2] == 's')
  564.     {
  565.       if (p[-4] != 'n' || p[-3] != 'e')
  566.     return (0);
  567.       if (len < 5)
  568.     return (0);
  569.       p[-4] = 0;        /* zap NESS */
  570.       if (p[-5] == 'i' && !isvowel (p[-6]))
  571.     {
  572.       p[-5] = 'y';
  573.       if ((h = lookup (w)))
  574.         {
  575.           if (entering)
  576.         add_flag (h, P_FLAG);
  577.           if (get_flags (h) & P_FLAG)
  578.         return (2);
  579.           return (0);
  580.         }
  581.       p[-5] = 'i';
  582.     }
  583.  
  584.       if (p[-5] == 'y' && !isvowel (p[-6]))
  585.     return (0);        /* stops shyness -> shy/p */
  586.  
  587.       if ((h = lookup (w)))
  588.     {
  589.       if (entering)
  590.         add_flag (h, P_FLAG);
  591.       if (get_flags (h) & P_FLAG)
  592.         return (2);
  593.     }
  594.  
  595.       return (0);
  596.     }
  597.  
  598.   if (p[-2] == 'r')
  599.     {
  600.       if (p[-3] != 'e')
  601.     return (0);
  602.       p[-2] = 0;
  603.       if ((h = lookup (w)))
  604.     {
  605.       if (entering)
  606.         add_flag (h, Z_FLAG);
  607.       if (get_flags (h) & Z_FLAG)
  608.         return (2);
  609.     }
  610.  
  611.       if (p[-4] != 'e')
  612.     {
  613.       if (p[-4] == 'i' && !isvowel (p[-5]))
  614.         p[-4] = 'y';
  615.       p[-3] = 0;
  616.       if ((h = lookup (w)))
  617.         {
  618.           if (entering)
  619.         add_flag (h, Z_FLAG);
  620.           if (get_flags (h) & Z_FLAG)
  621.         return (2);
  622.         }
  623.     }
  624.       return (0);
  625.     }
  626.  
  627.   if (p[-2] == 'g')
  628.     {
  629.       if (p[-4] != 'i' || p[-3] != 'n')
  630.     return (0);
  631.       p[-4] = 'e';
  632.       p[-3] = 0;
  633.       if ((h = lookup (w)))
  634.     {
  635.       if (entering)
  636.         add_flag (h, J_FLAG);
  637.       if (get_flags (h) & J_FLAG)
  638.         return (2);
  639.       return (0);
  640.     }
  641.  
  642.       if (len < 5)
  643.     return (0);
  644.       if (p[-5] == 'e')
  645.     return (0);
  646.       p[-4] = 0;
  647.  
  648.       if ((h = lookup (w)))
  649.     {
  650.       if (entering)
  651.         add_flag (h, J_FLAG);
  652.       if (get_flags (h) & J_FLAG)
  653.         return (2);
  654.     }
  655.       return (0);
  656.     }
  657.  
  658.   if (p[-2] == 'n')
  659.     {
  660.       if (p[-3] == 'e' && p[-4] != 'e' && p[-4] != 'y')
  661.     {
  662.       p[-3] = 0;
  663.       if ((h = lookup (w)))
  664.         {
  665.           if (entering)
  666.         add_flag (h, X_FLAG);
  667.           if (get_flags (h) & X_FLAG)
  668.         return (2);
  669.         }
  670.       return (0);
  671.     }
  672.  
  673.       if (p[-4] != 'i' || p[-3] != 'o')
  674.     return (0);
  675.       p[-4] = 'e';
  676.       p[-3] = 0;
  677.       if ((h = lookup (w)))
  678.     {
  679.       if (entering)
  680.         add_flag (h, X_FLAG);
  681.       if (get_flags (h) & X_FLAG)
  682.         return (2);
  683.     }
  684.  
  685.       if (len < 8)
  686.     return (0);
  687.       if (p[-8] != 'i')
  688.     return (0);
  689.       if (p[-7] != 'c')
  690.     return (0);
  691.       if (p[-6] != 'a')
  692.     return (0);
  693.       if (p[-5] != 't')
  694.     return (0);
  695.  
  696.       p[-8] = 'y';
  697.       p[-7] = 0;
  698.       if ((h = lookup (w)))
  699.     {
  700.       if (entering)
  701.         add_flag (h, X_FLAG);
  702.       if (get_flags (h) & X_FLAG)
  703.         return (2);
  704.     }
  705.     }
  706.   return (0);
  707. }
  708.  
  709. /* TIGHTEN, CREATION, MULIPLICATION */
  710. /* only the N flag */
  711. int
  712. n_ending (w, len)
  713.   char *w;
  714.   int len;
  715. {
  716.   char *p;
  717.   hash_index h;
  718.  
  719.   p = w + len;
  720.  
  721.   if (p[-2] == 'e')
  722.     {
  723.       if (p[-3] == 'e' || p[-3] == 'y')
  724.     return (0);
  725.       p[-2] = 0;
  726.       len -= 2;
  727.       if ((h = lookup (w)))
  728.     {
  729.       if (entering)
  730.         add_flag (h, N_FLAG);
  731.       if (get_flags (h) & N_FLAG)
  732.         return (2);
  733.     }
  734.       return (0);
  735.     }
  736.  
  737.   if (p[-3] != 'i')
  738.     return (0);
  739.   if (p[-2] != 'o')
  740.     return (0);
  741.   if (p[-1] != 'n')
  742.     return (0);
  743.  
  744.   p[-3] = 'e';
  745.   p[-2] = 0;
  746.   len -= 2;
  747.  
  748.   if ((h = lookup (w)))
  749.     {
  750.       if (entering)
  751.     add_flag (h, N_FLAG);
  752.       if (get_flags (h) & N_FLAG)
  753.     return (2);
  754.  
  755.       return (0);
  756.     }
  757.  
  758.   /* really against ICATION */
  759.   if (p[-7] != 'i')
  760.     return (0);
  761.   if (p[-6] != 'c')
  762.     return (0);
  763.   if (p[-5] != 'a')
  764.     return (0);
  765.   if (p[-4] != 't')
  766.     return (0);
  767.   if (p[-3] != 'e')
  768.     return (0);
  769.  
  770.   p[-7] = 'y';
  771.   p[-6] = 0;
  772.   len -= 4;
  773.  
  774.   if ((h = lookup (w)))
  775.     {
  776.       if (entering)
  777.     add_flag (h, N_FLAG);
  778.       if (get_flags (h) & N_FLAG)
  779.     return (2);
  780.     }
  781.  
  782.   return (0);
  783. }
  784.  
  785. /* FOR CREATIVE, PREVENTIVE */
  786. /* flags: v */
  787. int
  788. e_ending (w, len)
  789.   char *w;
  790.   int len;
  791. {
  792.   char *p;
  793.   hash_index h;
  794.  
  795.   p = w + len;
  796.  
  797.   if (p[-3] != 'i')
  798.     return (0);
  799.   if (p[-2] != 'v')
  800.     return (0);
  801.   if (p[-1] != 'e')
  802.     return (0);
  803.  
  804.   p[-3] = 'e';
  805.   p[-2] = 0;
  806.   len -= 2;
  807.  
  808.   if ((h = lookup (w)))
  809.     {
  810.       if (entering)
  811.     add_flag (h, V_FLAG);
  812.       if (get_flags (h) & V_FLAG)
  813.     return (2);
  814.       return (0);
  815.     }
  816.  
  817.   if (p[-4] == 'e')
  818.     return (0);
  819.  
  820.   p[-3] = 0;
  821.  
  822.   if ((h = lookup (w)))
  823.     {
  824.       if (entering)
  825.     add_flag (h, V_FLAG);
  826.       if (get_flags (h) & V_FLAG)
  827.     return (2);
  828.     }
  829.  
  830.   return (0);
  831. }
  832.  
  833. /* FOR QUICKLY */
  834. /* flags: y */
  835. int
  836. y_ending (w, len)
  837.   char *w;
  838.   int len;
  839. {
  840.   char *p;
  841.   hash_index h;
  842.  
  843.   p = w + len;
  844.  
  845.   if (p[-2] != 'l')
  846.     return (0);
  847.   if (p[-1] != 'y')
  848.     return (0);
  849.  
  850.   p[-2] = 0;
  851.   len -= 2;
  852.  
  853.   if ((h = lookup (w)))
  854.     {
  855.       if (entering)
  856.     add_flag (h, Y_FLAG);
  857.       if (get_flags (h) & Y_FLAG)
  858.     return (2);
  859.     }
  860.  
  861.   return (0);
  862. }
  863.